package com.wy._03Array;

/**
 * @author 吴宇~
 * @motto 我亦无他，唯手熟尔。
 * @edition jdk1.8
 * @reflection 0-1 喧闹任其喧闹，自由我自为之，我自风情万种，与世无争。
 * @date 2023/07/18/20:15
 * @target 心若有所向往，何惧道阻且长
 */

import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * 写关于自己的数组工具类
 * 泛型只能是引用类型，不能是基本数据类型
 * 在韩顺平的泛型课，559节醍醐灌顶，对于比较器，可能当时没有明白，但是现在明白了，6。
 * 使用泛型的数组不能进行初始化，因为不知道开辟多大的空间。
 * <p>
 * 因为静态是和类相关的，在类加载时。对象还没有创建，
 * 静态方法和静态属性不能使用泛型，jvm无法初始化，在创建对象的时候，没有指定泛型，默认是object
 * -------自定义泛型方法：
 * 可以在普通类中，也可以在泛型类中，
 * 泛型方法怎么调用呢。泛型方法一般在调用的时候指定类型， 就是在该方法的参数里面指定，对于这一个对象， 该方法里面就是这种类型了。
 * 泛型方法是在该方法前面申明了泛型，不是使用类里面的泛型，那个叫方法使用泛型，而不叫泛型方法
 * 泛型方法申明的泛型可以是自己重新申明，也可以是使用类里面的泛型，
 *
 * 总结：上面的问题解决了，关关难过关关过，也不需要刻意的去思考未知的东西，碰到啥，学啥，碰到啥，研究啥！！！！加油。
 */
@SuppressWarnings("all")
public class ArrayUtils {

    /**
     * 问题：不太对，如何使用泛型来替换这一部分，！！！！  使用泛型和class 类。直接生成类型，底层一定是反射那一套建立的，使用一个copy的方法解决 已解决
     */

    /**
     * 在数组最后添加一个元素
     * 使用泛型，传入一个泛型数组，和泛型元素，是调用一个方法，使这个数组数量加1.
     * 将这个泛型元素添加在最后面，虽然传入的类型是引用类型， 但是数组的规定是当创
     * 建的时候确定数组长度，就不能改变了，所以啊，只能返回一个新的数组，不能改变原
     * 来的数组长度，不像创建一个类一样，不能改变，只能通过返回一个新的数组来达到
     * 目的。
     *
     * @param ss  传泛型入数组
     * @param s   传入泛型元素
     * @param <S> 泛型随意
     * @return 返回泛型数组
     */
    public static <S> S[] push(S[] ss, S s) throws IllegalAccessException, InstantiationException {
        if (null == ss || ss.length == 0) {
            throw new RuntimeException("数组异常");
        }
        S[] newArray = Arrays.copyOf(ss, ss.length + 1);
        newArray[newArray.length - 1] = s;
        return newArray;
    }

    /**
     * 和上面的push运行结果一样但是不一样的是使用的泛型创建了对象。
     *
     * @param ss
     * @param s
     * @param <S>
     * @return
     */
    public static <S> S[] push_(S[] ss, S s) {
        if (null == ss || ss.length == 0) {
            throw new RuntimeException("数组异常");
        }
        //根据类型得到一个新的数组
        S[] newArray = (S[]) Array.newInstance(ss.getClass().getComponentType(), ss.length + 1);
        for (int i = 0; i < ss.length; i++) {
            newArray[i] = ss[i];
        }
        newArray[newArray.length - 1] = s;
        return newArray;
    }

    /**
     * 传入一个intger类型的数组，和该类型的元素，创建新的数组将原数组拷贝将最后一个元素添加在最后并返回该数组，
     *
     * @param integers
     * @param integer
     * @return
     */
    public Integer[] intAdd(Integer[] integers, Integer integer) {
        Integer[] integers1 = Arrays.copyOf(integers, integers.length);
        integers1[integers1.length - 1] = integer;
        return integers1;
    }

    /**
     * 通过泛型的方式根据位置参数和删除元素个数参数来得到新的数组
     * 传入开始删除的位置和删除的个数
     *
     * @param fs
     * @param position
     * @param num
     * @param <F>
     * @return
     */
    public static <F> F[] SpecifyDeletion(F[] fs, int position, int num) {
        if (!(fs != null && fs.length != 0)) {
            throw new RuntimeException("数组异常");
        }
        if (position < 0 || num <= 0) {
            throw new RuntimeException("传入参数异常");
        }
        /**
         * 这句代码直接封神；从哪儿学的。自己  从   源码学的！！！！我为什么觉得这样可以，与mybatis-plus里面的lambda表达式有点关系。
         */
        F[] f = (F[]) Array.newInstance(fs.getClass().getComponentType(), fs.length - num);
        for (int i = 0; i < f.length; i++) {
            f[i] = null;
        }
        for (int i = 0; i < position; i++) {
            f[i] = fs[i];
        }
        for (int i = position, j = position + num; i < f.length; i++, j++) {
            f[i] = fs[j];
        }
        return f;
    }

    /**
     * 传入一个数组，传入数组位置。0开头，传入删除元素数量，这样不是泛型，是确定类型的数组
     *
     * @param ints 传入的数组
     * @param pos  开始删除的位置
     * @param nums 删除的数量
     * @return 新的数组
     */
    public static int[] intsDelete(Integer[] ints, int pos, int nums) {
        if (!(ints != null && ints.length != 0)) {
            throw new RuntimeException("数组异常");
        }
        if (pos < 0 || nums <= 0) {
            throw new RuntimeException("传入参数异常");
        }
        int[] ints1 = new int[ints.length - nums];
        for (int i = 0; i < ints1.length; i++) {
            ints1[i] = 0;
        }
        for (int i = 0; i < pos; i++) {
            ints1[i] = ints[i];
        }
        for (int i = pos, j = pos + nums; i < ints1.length; i++, j++) {
            ints1[i] = ints[j];
        }

        return ints1;
    }

    /**
     * 泛型方法，方法中定义的泛型，
     *
     * @param f
     * @param r
     * @param <F>
     * @param <R>
     * @return
     */
    public static <F, R> F[] fly(F f, R r) {
        //这样即可以的得到一个F类型的数组！！！可以指定长度。
        Integer[] o = (Integer[]) Array.newInstance(f.getClass().getComponentType(), 12);
        return null;
    }
}
